package com.hsc.www.hello;

import org.springframework.core.MethodParameter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class UserIdArgumentResolver extends RequestResponseBodyMethodProcessor {

    public UserIdArgumentResolver(List<HttpMessageConverter<?>> converters) {
        super(converters);
    }

    public UserIdArgumentResolver(List<HttpMessageConverter<?>> converters, ContentNegotiationManager manager) {
        super(converters, manager);
    }

    public UserIdArgumentResolver(List<HttpMessageConverter<?>> converters, List<Object> requestResponseBodyAdvice) {
        super(converters, requestResponseBodyAdvice);
    }

    public UserIdArgumentResolver(List<HttpMessageConverter<?>> converters, ContentNegotiationManager manager, List<Object> requestResponseBodyAdvice) {
        super(converters, manager, requestResponseBodyAdvice);
    }

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        Class<?> paramType = parameter.getParameterType();
        return paramType.isInterface() && Pojo.class.isAssignableFrom(paramType);

    }

    @Override
    public Object resolveArgument(MethodParameter parameter,
                                  ModelAndViewContainer mavContainer,
                                  NativeWebRequest webRequest,
                                  WebDataBinderFactory binderFactory) throws Exception {

        super.resolveArgument(parameter,
                 mavContainer,
                 webRequest,
                 binderFactory);
        Class<?> paramType = parameter.getParameterType();
        InvocationHandler  invocationHandler=new ProxyInvocationHandler(parameter,mavContainer,webRequest,binderFactory);
        Object instance=  Proxy.newProxyInstance(
                paramType.getClassLoader(),
                new Class[] {paramType},
                invocationHandler);
        return  instance;


    }


    static  class  ProxyInvocationHandler implements InvocationHandler{

      private   MethodParameter parameter;
      private   ModelAndViewContainer mavContainer;
      private   NativeWebRequest webRequest;
      private   WebDataBinderFactory binderFactory;

      private Map<String ,Object> cache=new HashMap<>();


      public ProxyInvocationHandler(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
          this.parameter = parameter;
          this.mavContainer = mavContainer;
          this.webRequest = webRequest;
          this.binderFactory = binderFactory;
      }

      @Override
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            String name=method.getName();
            if (name.startsWith("get")){
                return cache.get(name.substring(3));
            }else if (name.startsWith("set")){
                return    cache.put(name.substring(3),args[0]);
            }else{
                return null;
            }
      }
    }


}
